package rollup

import (
	"crypto/ecdsa"
	"crypto/elliptic"
	"crypto/rand"
	"crypto/sha256"
	"encoding/binary"

	"github.com/consensys/gnark/frontend"
)

type RequestConstraints struct {
	Data      frontend.Variable
	Nonce     frontend.Variable
	PubKey    ecdsa.PublicKey
	Signature []byte
}

type Request struct {
	Nonce     uint64 // sum from zero
	Data      []byte // feature extracting result hash
	PubKey    ecdsa.PublicKey
	Signature []byte
}

func NewRequest() *Request {
	var req Request
	req.Nonce = 0
	privKey, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
	req.PubKey = privKey.PublicKey
	req.PubKey.X.SetUint64(0)
	req.PubKey.Y.SetUint64(0)
	return &req
}

func DeserializeRequest(data []byte) (res *Request, err error) {

	defer func(res *Request, err error) (*Request, error) {
		if err := recover(); err != nil {
			return nil, err.(error)
		} else {
			return res, nil
		}

	}(res, err)

	res = NewRequest()
	res.Nonce = binary.BigEndian.Uint64(data[:8])
	res.Data = data[8:40]
	res.PubKey.X.SetBytes(data[40:72])
	res.PubKey.Y.SetBytes(data[72:104])
	res.Signature = data[104:]

	return res, err
}

func (req *Request) Verify() bool {

	var res [104]byte
	binary.BigEndian.PutUint64(res[0:8], req.Nonce)
	copy(res[8:], req.Data[:])
	buf := req.PubKey.X.Bytes()
	copy(res[40:], buf[:])
	buf = req.PubKey.Y.Bytes()
	copy(res[72:], buf[:])

	hash := sha256.New()
	hash.Write(res[:])
	return ecdsa.VerifyASN1(&req.PubKey, hash.Sum([]byte{}), req.Signature)
}
